home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / fsrmt / fsrmtFile.c < prev    next >
C/C++ Source or Header  |  1991-07-01  |  52KB  |  1,746 lines

  1. /* 
  2.  * fsRmtFile.c --
  3.  *
  4.  *    Routines for operations on remote files.  The I/O operations
  5.  *    check in the cache, and then use the raw remote I/O operations
  6.  *    to transfer data to and from the remote file server.
  7.  *
  8.  * Copyright 1987 Regents of the University of California
  9.  * All rights reserved.
  10.  * Permission to use, copy, modify, and distribute this
  11.  * software and its documentation for any purpose and without
  12.  * fee is hereby granted, provided that the above copyright
  13.  * notice appear in all copies.  The University of California
  14.  * makes no representations about the suitability of this
  15.  * software for any purpose.  It is provided "as is" without
  16.  * express or implied warranty.
  17.  */
  18.  
  19. #ifndef lint
  20. static char rcsid[] = "$Header: /sprite/src/kernel/fsrmt/RCS/fsrmtFile.c,v 1.4 91/07/01 14:36:53 mgbaker Exp $ SPRITE (Berkeley)";
  21. #endif not lint
  22.  
  23.  
  24. #include <sprite.h>
  25. #include <fs.h>
  26. #include <fsutil.h>
  27. #include <fsconsist.h>
  28. #include <fsioFile.h>
  29. #include <fslcl.h>
  30. #include <fscache.h>
  31. #include <fsdm.h>
  32. #include <fsStat.h>
  33. #include <fsprefix.h>
  34. #include <fsNameOps.h>
  35. #include <fsrmt.h>
  36.  
  37. #include <rpc.h>
  38. #include <vm.h>
  39.  
  40. #include <stdio.h>
  41.  
  42. static ReturnStatus FsrmtFileBlockRead _ARGS_((Fs_HandleHeader *hdrPtr, 
  43.         Fscache_Block *blockPtr, Sync_RemoteWaiter *waitPtr));
  44. static ReturnStatus FsrmtFileBlockWrite _ARGS_((Fs_HandleHeader *hdrPtr, 
  45.         Fscache_Block *blockPtr, int flags));
  46. static ReturnStatus FsrmtFileBlockAllocate _ARGS_((Fs_HandleHeader *hdrPtr, 
  47.         int offset, int numBytes, int flags, int *blockAddrPtr, 
  48.         Boolean *newBlockPtr));
  49. static ReturnStatus FsrmtFileTrunc _ARGS_((Fs_HandleHeader *hdrPtr, int size,
  50.                       Boolean delete));
  51. static Boolean FsrmtStartWriteBack _ARGS_((Fscache_Backend *backendPtr));
  52.  
  53. static void FsrmtReallocBlock _ARGS_((ClientData data, 
  54.         Proc_CallInfo *callInfoPtr));
  55.  
  56. static Fscache_BackendRoutines  fsrmtBackendRoutines = {
  57.         FsrmtFileBlockAllocate,
  58.         FsrmtFileTrunc,
  59.         FsrmtFileBlockRead,
  60.         FsrmtFileBlockWrite,
  61.         FsrmtReallocBlock,
  62.         FsrmtStartWriteBack,
  63.  
  64. };
  65. static     Fscache_Backend *cacheBackendPtr = (Fscache_Backend *) NIL;
  66.  
  67. static Boolean FileMatch _ARGS_((Fscache_FileInfo *cacheInfoPtr, 
  68.         ClientData cleintData));
  69. static Boolean BlockMatch _ARGS_((Fscache_Block *blockPtr,
  70.         ClientData cleintData));
  71.  
  72. static Sync_Lock rmtCleanerLock = Sync_LockInitStatic("Fs:rmtCleanerLock");
  73. #define    LOCKPTR    &rmtCleanerLock
  74.  
  75. int    fsrmtBlockCleaners = 0;
  76.  
  77. #ifdef SOSP91
  78. Fs_NewStats    fs_MoreStats;
  79. #endif SOSP91
  80.  
  81.  
  82. /*
  83.  *----------------------------------------------------------------------
  84.  *
  85.  * FsRmtFileHandleInit --
  86.  *
  87.  *    Initialize a handle for a remote file from the file state
  88.  *    returned by the server.
  89.  *
  90.  * Results:
  91.  *    SUCCESS.
  92.  *
  93.  * Side effects:
  94.  *    Create and install a handle for the file.
  95.  *
  96.  *----------------------------------------------------------------------
  97.  */
  98. ReturnStatus
  99. FsRmtFileHandleInit(fileIDPtr, fileStatePtr, openForWriting, name,
  100.     newHandlePtrPtr)
  101.     Fs_FileID        *fileIDPtr;
  102.     Fsio_FileState        *fileStatePtr;
  103.     Boolean        openForWriting;
  104.     char        *name;
  105.     Fsrmt_FileIOHandle    **newHandlePtrPtr;
  106. {
  107.     register Fsrmt_FileIOHandle *handlePtr;
  108.     Boolean found;
  109.  
  110.     found = Fsutil_HandleInstall(fileIDPtr, sizeof(Fsrmt_FileIOHandle), name,
  111.             FALSE, (Fs_HandleHeader **)newHandlePtrPtr);
  112.     handlePtr = *newHandlePtrPtr;
  113.     if (found) {
  114.     /*
  115.      * Update attributes cached in the handle, and verify the
  116.      * validity of any cached data blocks.
  117.      */
  118.     if (Fscache_UpdateFile(&handlePtr->cacheInfo, openForWriting,
  119.             fileStatePtr->version, fileStatePtr->cacheable,
  120.             &fileStatePtr->attr)) {
  121.         Vm_FileChanged(&handlePtr->segPtr);
  122.     }
  123.     /* 
  124.      * Update the handle's open time stamp.  This is used to catch races
  125.      * between near-simultanous opens on a client and related cache
  126.      * consistency messasge.
  127.      */
  128.     if (fileStatePtr->openTimeStamp > handlePtr->openTimeStamp) {
  129.         handlePtr->openTimeStamp = fileStatePtr->openTimeStamp;
  130.     }
  131.     } else {
  132.     if (cacheBackendPtr == (Fscache_Backend *) NIL) {
  133.         cacheBackendPtr = 
  134.         Fscache_RegisterBackend(&fsrmtBackendRoutines,(ClientData)0,0);
  135.     }
  136.     /*
  137.      * Initialize the new handle.  There is no cache validation to
  138.      * be done because blocks are only cached when a handle is present.
  139.      */
  140.     Fscache_FileInfoInit(&handlePtr->cacheInfo, (Fs_HandleHeader *)handlePtr,
  141.         fileStatePtr->version, fileStatePtr->cacheable,
  142.         &fileStatePtr->attr, cacheBackendPtr);
  143.  
  144.     Fsutil_RecoveryInit(&handlePtr->rmt.recovery);
  145.     Fscache_ReadAheadInit(&handlePtr->readAhead);
  146.  
  147.     handlePtr->flags = 0;
  148.     handlePtr->openTimeStamp = fileStatePtr->openTimeStamp;
  149.     handlePtr->segPtr = (Vm_Segment *)NIL;
  150.     fs_Stats.object.rmtFiles++;
  151.     }
  152. #ifdef SOSP91
  153.     if (fileStatePtr->newUseFlags & FS_DIR) {
  154.     handlePtr->cacheInfo.flags |= FSCACHE_IS_DIR;
  155.     }
  156. #endif SOSP91
  157.     free((Address)fileStatePtr);
  158.     return(SUCCESS);
  159. }
  160.  
  161. /*
  162.  *----------------------------------------------------------------------
  163.  *
  164.  * FsrmtFileIoOpen --
  165.  *
  166.  *      Set up a stream for a remote disk file.  This is called from Fs_Open
  167.  *    to complete the opening of a stream. By this time any cache consistency
  168.  *    actions have already been taken.
  169.  *
  170.  * Results:
  171.  *    SUCCESS, until FsRmtFileHandleInit returns differently.
  172.  *
  173.  * Side effects:
  174.  *    Installs the handle for the file and updates the use counts
  175.  *    (ref, write, exec) due to this open.
  176.  *
  177.  *----------------------------------------------------------------------
  178.  */
  179. /*ARGSUSED*/
  180. ReturnStatus
  181. FsrmtFileIoOpen(ioFileIDPtr, flagsPtr, clientID, streamData, name,
  182.     ioHandlePtrPtr)
  183.     Fs_FileID        *ioFileIDPtr;    /* I/O fileID from the name server */
  184.     int            *flagsPtr;    /* New ones from the server returned */
  185.     int            clientID;    /* IGNORED */
  186.     ClientData        streamData;    /* Reference to Fsio_FileState struct */
  187.     char        *name;        /* File name for error msgs */
  188.     Fs_HandleHeader    **ioHandlePtrPtr;/* Return - a handle set up for
  189.                      * I/O to a file, NIL if failure. */
  190. {
  191.     ReturnStatus        status;
  192.     Fsio_FileState            *fileStatePtr;
  193.     register int         flags;
  194.     register Fsrmt_FileIOHandle *rmtHandlePtr;
  195.  
  196.     fileStatePtr = (Fsio_FileState *)streamData;
  197.     flags = fileStatePtr->newUseFlags;
  198.  
  199.     status = FsRmtFileHandleInit(ioFileIDPtr, fileStatePtr,
  200.         (flags & FS_WRITE), name, (Fsrmt_FileIOHandle **)ioHandlePtrPtr);
  201.     if (status == SUCCESS) {
  202.     rmtHandlePtr = (Fsrmt_FileIOHandle *)*ioHandlePtrPtr;
  203.     /*
  204.      * Update our use information to reflect the open.
  205.      */
  206.     rmtHandlePtr->rmt.recovery.use.ref++;
  207.     if (flags & FS_WRITE) {
  208.         rmtHandlePtr->rmt.recovery.use.write++;
  209.     }
  210.     if (flags & FS_EXECUTE) {
  211.         rmtHandlePtr->rmt.recovery.use.exec++;
  212.     }
  213.     /*
  214.      * Note if we are a swap file in case of recovery later.
  215.      */
  216.     rmtHandlePtr->flags |= (flags & FS_SWAP);
  217.     *flagsPtr = flags;
  218.     Fsutil_HandleUnlock(rmtHandlePtr);
  219.     }
  220.     return(status);
  221. }
  222.  
  223. /*
  224.  *----------------------------------------------------------------------
  225.  *
  226.  * FsrmtFileReopen --
  227.  *
  228.  *    Reopen a remote file.  This sets up and conducts an 
  229.  *    RPC_FS_REOPEN remote procedure call to re-open the remote file.
  230.  *
  231.  * Results:
  232.  *    A  non-SUCCESS return code if the re-open was attempted and failed.
  233.  *    FS_NO_HANDLE if we delete the handle.
  234.  *
  235.  * Side effects:
  236.  *    If the reopen works we'll have updated cached attributes, version
  237.  *    number, etc.
  238.  *
  239.  *----------------------------------------------------------------------
  240.  */
  241. /*ARGSUSED*/
  242. ReturnStatus
  243. FsrmtFileReopen(hdrPtr, clientID, inData, outSizePtr, outDataPtr)
  244.     Fs_HandleHeader    *hdrPtr;
  245.     int            clientID;        /* Should be rpc_SpriteID */
  246.     ClientData        inData;            /* IGNORED */
  247.     int            *outSizePtr;        /* IGNORED */
  248.     ClientData        *outDataPtr;        /* IGNORED */
  249. {
  250.     register Fsrmt_FileIOHandle    *rmtHandlePtr;
  251.     ReturnStatus        status;
  252.     Fsio_FileReopenParams        reopenParams;
  253.     Fsio_FileState            fileState;
  254.     register int        numDirtyBlocks;
  255.     int                outSize;
  256.  
  257.     rmtHandlePtr = (Fsrmt_FileIOHandle *)hdrPtr;
  258.     numDirtyBlocks = Fscache_PreventWriteBacks(&rmtHandlePtr->cacheInfo);
  259.     Fscache_AllowWriteBacks(&rmtHandlePtr->cacheInfo);
  260.     /*
  261.      * Optimize out re-opens for files that aren't being waited
  262.      * on, that have no users, and that have no blocks in the cache.
  263.      * I don't call OkToScavenge from fsutilHandleScavenge.c, since I think
  264.      * it's okay to do this even if there's already an active scavenger,
  265.      * because it will have locked the handle if it's working on it.
  266.      */
  267.     if (rmtHandlePtr->rmt.recovery.use.ref == 0 &&
  268.         Fscache_OkToScavenge(&rmtHandlePtr->cacheInfo) &&
  269.         !Fsutil_RecoveryNeeded(&rmtHandlePtr->rmt.recovery)) {
  270.         Vm_FileChanged(&rmtHandlePtr->segPtr);
  271.         Fsutil_RecoverySyncLockCleanup(&rmtHandlePtr->rmt.recovery);
  272.         Fscache_InfoSyncLockCleanup(&rmtHandlePtr->cacheInfo);
  273.         Fscache_ReadAheadSyncLockCleanup(&rmtHandlePtr->readAhead);
  274.         Fsutil_HandleRemove(rmtHandlePtr);
  275.         fs_Stats.object.rmtFiles--;
  276.     fs_Stats.recovery.reopensAvoided++;
  277.     return FS_NO_HANDLE;
  278.     }
  279. /* for debugging */
  280. #define    FS_HANDLE_INVALID 0x20
  281.     if (hdrPtr->flags & FS_HANDLE_INVALID) {
  282.     printf("Attempting to recover invalid file handle <%d,0x%x,0x%x>\n",
  283.         hdrPtr->fileID.serverID, hdrPtr->fileID.major,
  284.         hdrPtr->fileID.minor);
  285.     return SUCCESS;
  286.     }
  287. /* end for debugging */
  288.     reopenParams.flags = rmtHandlePtr->flags;
  289.     if (numDirtyBlocks > 0) {
  290.     reopenParams.flags |= FSIO_HAVE_BLOCKS;
  291.     }
  292.     reopenParams.fileID = hdrPtr->fileID;
  293.     reopenParams.fileID.type = FSIO_LCL_FILE_STREAM;
  294.     reopenParams.prefixFileID.type = NIL;    /* not used */
  295.     reopenParams.use = rmtHandlePtr->rmt.recovery.use;
  296.     reopenParams.version = rmtHandlePtr->cacheInfo.version;
  297.  
  298.     /*
  299.      * Contact the server to do the reopen.  We have to unlock the handle
  300.      * here in case the server asks us to write-back or invalidate.
  301.      */
  302.     outSize = sizeof(Fsio_FileState);
  303.     Fsutil_HandleUnlock(hdrPtr);
  304.     status = FsrmtReopen(hdrPtr, sizeof(Fsio_FileReopenParams),
  305.         (Address)&reopenParams, &outSize, (Address)&fileState);
  306.     Fsutil_HandleLock(hdrPtr);
  307.     if (status != SUCCESS) {
  308.     if (numDirtyBlocks > 0) {
  309.         printf(
  310. "Re-open failed <%x> with dirty blocks in cache, \"%s\" <%d,%d> server %d\n",
  311.         status, Fsutil_HandleName(hdrPtr), hdrPtr->fileID.major,
  312.         hdrPtr->fileID.minor, hdrPtr->fileID.serverID);
  313.     }
  314.     if (status != RPC_TIMEOUT &&
  315.         status != RPC_SERVICE_DISABLED) {
  316.         /*
  317.          * Nuke the cache because our caller will nuke the handle.
  318.          */
  319.         Fscache_FileInvalidate(&rmtHandlePtr->cacheInfo, 0, FSCACHE_LAST_BLOCK);
  320.     }
  321.     } else {
  322.     /*
  323.      * Flush any lanquishing dirty blocks back to the server.
  324.      */
  325.     if (numDirtyBlocks > 0) {
  326.         int skipped;
  327. #ifdef SOSP91
  328.         rmtHandlePtr->cacheInfo.flags |= FSCACHE_REOPEN;
  329. #endif SOSP91
  330.         (void) Fscache_FileWriteBack(&rmtHandlePtr->cacheInfo, 0,
  331.                 FSCACHE_LAST_BLOCK, 0, &skipped);
  332.     }
  333.     /*
  334.      * Update the handle - take care of cache flushes, updating cached
  335.      * attributes, etc.
  336.      */
  337.     if (Fscache_UpdateFile(&rmtHandlePtr->cacheInfo,
  338.             rmtHandlePtr->rmt.recovery.use.write,
  339.             fileState.version, fileState.cacheable,
  340.             &fileState.attr)) {
  341.         Vm_FileChanged(&rmtHandlePtr->segPtr);
  342.     }
  343.  
  344.     rmtHandlePtr->openTimeStamp = fileState.openTimeStamp;
  345.     }
  346.     return(status);
  347. }
  348.  
  349. /*
  350.  *----------------------------------------------------------------------
  351.  *
  352.  * FsrmtFileClose -- 
  353.  *
  354.  *    Close time processing for remote files.
  355.  *
  356.  * Results:
  357.  *    SUCCESS.
  358.  *
  359.  * Side effects:
  360.  *    This decrements the local use counts, then synchronizes
  361.  *    with write-backs before telling the server about the close.
  362.  *
  363.  *----------------------------------------------------------------------
  364.  */
  365.  
  366. /*ARGSUSED*/
  367. #ifndef SOSP91
  368. ReturnStatus
  369. FsrmtFileClose(streamPtr, clientID, procID, flags, dataSize, closeData)
  370. #else
  371. ReturnStatus
  372. FsrmtFileClose(streamPtr, clientID, procID, flags, dataSize, closeData,
  373.     offsetPtr, rwFlagsPtr)
  374. #endif
  375.     Fs_Stream        *streamPtr;    /* Stream to remote file */
  376.     int            clientID;    /* HostID of client closing */
  377.     Proc_PID        procID;        /* Process ID of closer */
  378.     int            flags;        /* Flags from the stream being closed */
  379.     int            dataSize;    /* Size of closeData */
  380.     ClientData        closeData;    /* NIL on entry. */
  381. #ifdef SOSP91
  382.     int            *offsetPtr;    /* Not used. */
  383.     int            *rwFlagsPtr;    /* Not used. */
  384. #endif
  385. {
  386.     register ReturnStatus status;
  387.     register Fsrmt_FileIOHandle *handlePtr =
  388.         (Fsrmt_FileIOHandle *)streamPtr->ioHandlePtr;
  389.     /*
  390.      * Decrement local references.
  391.      */
  392.  
  393.     handlePtr->rmt.recovery.use.ref--;
  394.     if (flags & FS_WRITE) {
  395.     handlePtr->rmt.recovery.use.write--;
  396.     }
  397.     if (flags & FS_EXECUTE) {
  398.     handlePtr->rmt.recovery.use.exec--;
  399.     }
  400.     if (handlePtr->rmt.recovery.use.ref < 0 ||
  401.     handlePtr->rmt.recovery.use.write < 0 ||
  402.     handlePtr->rmt.recovery.use.exec < 0) {
  403.     panic("FsrmtFileClose: <%d,%d> ref %d write %d exec %d\n",
  404.         handlePtr->rmt.hdr.fileID.major, handlePtr->rmt.hdr.fileID.minor,
  405.         handlePtr->rmt.recovery.use.ref,
  406.         handlePtr->rmt.recovery.use.write,
  407.         handlePtr->rmt.recovery.use.exec);
  408.     }
  409.     if (!Fsutil_HandleValid((Fs_HandleHeader *)handlePtr)) {
  410.     status = FS_FILE_REMOVED;
  411.     } else {
  412.     if (handlePtr->rmt.recovery.use.ref == 0) {
  413.         /*
  414.          * Synchronize closes and delayed writes.  We wait for writes
  415.          * in progress to complete. 
  416.          */
  417.         (void) Fscache_PreventWriteBacks(&handlePtr->cacheInfo);
  418.     }
  419.     status = Fsrmt_Close(streamPtr, clientID, procID, flags,
  420.         sizeof(Fscache_Attributes), (ClientData)&handlePtr->cacheInfo.attr);
  421.     }
  422.  
  423.     if (status == FS_FILE_REMOVED && handlePtr->rmt.recovery.use.ref == 0) {
  424.     /*
  425.      * Nuke our cache after we've finished with this (now bogus) handle.
  426.      * (Apparently we let the handle linger and get scavenged.  Could
  427.      * change things to remove the handle here.)
  428.      */
  429.     Fscache_Trunc(&handlePtr->cacheInfo, 0, FSCACHE_TRUNC_DELETE);
  430.     }
  431.     Fscache_AllowWriteBacks(&handlePtr->cacheInfo);
  432.     Fsutil_HandleRelease(handlePtr, TRUE);
  433.     return(SUCCESS);
  434. }
  435.  
  436. /*
  437.  *----------------------------------------------------------------------
  438.  *
  439.  * FsrmtFileScavenge --
  440.  *
  441.  *    Called peridocally to see if we still need the handle for
  442.  *    the remote file.
  443.  *
  444.  * Results:
  445.  *    TRUE if it removed the handle.
  446.  *
  447.  * Side effects:
  448.  *    Either removes or unlocks the handle.
  449.  *
  450.  *----------------------------------------------------------------------
  451.  */
  452. Boolean
  453. FsrmtFileScavenge(hdrPtr)
  454.     Fs_HandleHeader *hdrPtr;
  455. {
  456.     register Fsrmt_FileIOHandle *handlePtr = (Fsrmt_FileIOHandle *)hdrPtr;
  457.     if (handlePtr->rmt.recovery.use.ref == 0 &&
  458.     Fscache_OkToScavenge(&handlePtr->cacheInfo) &&
  459.     !Fsutil_RecoveryNeeded(&handlePtr->rmt.recovery)) {
  460.     /*
  461.      * Remove handles for files with no users and no blocks in cache.
  462.      */
  463.     Vm_FileChanged(&handlePtr->segPtr);
  464.     Fsutil_RecoverySyncLockCleanup(&handlePtr->rmt.recovery);
  465.     Fscache_InfoSyncLockCleanup(&handlePtr->cacheInfo);
  466.     Fscache_ReadAheadSyncLockCleanup(&handlePtr->readAhead);
  467.     Fsutil_HandleRemove(handlePtr);
  468.     fs_Stats.object.rmtFiles--;
  469.     return(TRUE);
  470.     } else {
  471.     Fsutil_HandleUnlock(handlePtr);
  472.     return(FALSE);
  473.     }
  474. }
  475.  
  476. /*
  477.  *----------------------------------------------------------------------
  478.  *
  479.  * FsrmtFileVerify --
  480.  *
  481.  *    Map from a remote client's fileID to a local fileID and
  482.  *    verify that the remote client is known.
  483.  *
  484.  * Results:
  485.  *    A pointer to the local handle for the file, or NIL if
  486.  *    the client is bad.
  487.  *
  488.  * Side effects:
  489.  *    Changes the client's fileID type to FSIO_LCL_FILE_STREAM and
  490.  *    fetches the local handle.  The handle is returned locked.
  491.  *
  492.  *----------------------------------------------------------------------
  493.  */
  494.  
  495. Fs_HandleHeader *
  496. FsrmtFileVerify(fileIDPtr, clientID, domainTypePtr)
  497.     Fs_FileID    *fileIDPtr;    /* Client's fileID */
  498.     int        clientID;    /* Host ID of the client */
  499.     int        *domainTypePtr;    /* Return - FS_LOCAL_DOMAIN */
  500. {
  501.     register Fsio_FileIOHandle *handlePtr;
  502.     register Fsconsist_ClientInfo    *clientPtr;
  503.     Boolean            found = FALSE;
  504.  
  505.     fileIDPtr->type = FSIO_LCL_FILE_STREAM;
  506.     handlePtr = Fsutil_HandleFetchType(Fsio_FileIOHandle, fileIDPtr);
  507.     if (handlePtr != (Fsio_FileIOHandle *)NIL) {
  508.     LIST_FORALL(&handlePtr->consist.clientList, (List_Links *) clientPtr) {
  509.         if (clientPtr->clientID == clientID) {
  510.         found = TRUE;
  511.         break;
  512.         }
  513.     }
  514.     if (!found) {
  515.         printf(
  516.         "FsrmtFileVerify: \"%s\" <%d,%d> client %d not found\n",
  517.         Fsutil_HandleName(handlePtr), fileIDPtr->major, fileIDPtr->minor,
  518.         clientID);
  519.         Fsutil_HandleRelease(handlePtr, TRUE);
  520.         handlePtr = (Fsio_FileIOHandle *)NIL;
  521.     }
  522.     } else {
  523.     printf( "FsrmtFileVerify, no handle <%d,%d> client %d\n",
  524.         fileIDPtr->major, fileIDPtr->minor, clientID);
  525.     }
  526.     if (domainTypePtr != (int *)NIL) {
  527.     *domainTypePtr = FS_LOCAL_DOMAIN;
  528.     }
  529.     return((Fs_HandleHeader *)handlePtr);
  530. }
  531.  
  532. /*
  533.  * ----------------------------------------------------------------------------
  534.  *
  535.  * FsrmtFileMigClose --
  536.  *
  537.  *    Release recovery use counts on a remote file.  This is called when
  538.  *    a stream to the file has migrated away.
  539.  *
  540.  * Results:
  541.  *    SUCCESS.
  542.  *
  543.  * Side effects:
  544.  *    Decrement use counts and release the handle.
  545.  *
  546.  * ----------------------------------------------------------------------------
  547.  *
  548.  */
  549. /*ARGSUSED*/
  550. ReturnStatus
  551. FsrmtFileMigClose(hdrPtr, flags)
  552.     Fs_HandleHeader *hdrPtr;    /* File being encapsulated */
  553.     int flags;            /* Use flags from the stream */
  554. {
  555.     register Fsrmt_FileIOHandle *handlePtr = (Fsrmt_FileIOHandle *)hdrPtr;
  556.  
  557.     Fsutil_HandleLock(handlePtr);
  558.     handlePtr->rmt.recovery.use.ref--;
  559.     if (flags & FS_WRITE) {
  560.     handlePtr->rmt.recovery.use.write--;
  561.     }
  562.     if (flags & FS_EXECUTE) {
  563.     handlePtr->rmt.recovery.use.exec--;
  564.     }
  565.     Fsutil_HandleRelease(handlePtr, TRUE);
  566.     return(SUCCESS);
  567. }
  568.  
  569. /*
  570.  * ----------------------------------------------------------------------------
  571.  *
  572.  * FsrmtFileMigOpen --
  573.  *
  574.  *    Complete the creation of a FSIO_RMT_FILE_STREAM after migration.
  575.  *    
  576.  * Results:
  577.  *    SUCCESS (until FsRmtFileHandleInit returns differently)
  578.  *
  579.  * Side effects:
  580.  *    If SUCCESS, adds a reference and useCounts to the I/O handle.
  581.  *
  582.  * ----------------------------------------------------------------------------
  583.  *
  584.  */
  585. /*ARGSUSED*/
  586. ReturnStatus
  587. FsrmtFileMigOpen(migInfoPtr, size, data, hdrPtrPtr)
  588.     Fsio_MigInfo    *migInfoPtr;    /* Migration state */
  589.     int        size;        /* sizeof(Fsio_FileState), IGNORED */
  590.     ClientData    data;        /* Ref. to Fsio_FileState. */
  591.     Fs_HandleHeader **hdrPtrPtr;    /* Return - I/O handle for the file */
  592. {
  593.     ReturnStatus status;
  594.     register Fs_FileID *fileIDPtr = &migInfoPtr->ioFileID;
  595.     Fsrmt_FileIOHandle *handlePtr;
  596.  
  597.     status = FsrmtFileIoOpen(fileIDPtr, &migInfoPtr->flags, rpc_SpriteID,
  598.         data, (char *)NIL, (Fs_HandleHeader **)&handlePtr);
  599.     *hdrPtrPtr = (Fs_HandleHeader *)handlePtr;
  600.     return(status);
  601. }
  602.  
  603. /*
  604.  * ----------------------------------------------------------------------------
  605.  *
  606.  * FsrmtFileMigrate --
  607.  *
  608.  *    This causes a call to Fsio_FileMigrate on the server to shift
  609.  *    client references.  We may be the server after migration, in which
  610.  *    case the routine is called directly.  Otherwise an RPC is done
  611.  *    to the server. A useful side-effect of this routine is
  612.  *    to properly set the type in the ioFileID, either FSIO_LCL_FILE_STREAM
  613.  *    or FSIO_RMT_FILE_STREAM.
  614.  *
  615.  * Results:
  616.  *    The return code from Fsio_FileMigrate, or the RPC.
  617.  *    Returns Fsio_FileState for use by the MigEnd routine.
  618.  *
  619.  * Side effects:
  620.  *    Sets the correct stream type on the ioFileID.
  621.  *
  622.  * ----------------------------------------------------------------------------
  623.  *
  624.  */
  625. /*ARGSUSED*/
  626. ReturnStatus
  627. FsrmtFileMigrate(migInfoPtr, dstClientID, flagsPtr, offsetPtr, sizePtr, dataPtr)
  628.     Fsio_MigInfo    *migInfoPtr;    /* Migration state */
  629.     int        dstClientID;    /* ID of target client */
  630.     int        *flagsPtr;    /* In/Out Stream usage flags */
  631.     int        *offsetPtr;    /* Return - the correct stream offset */
  632.     int        *sizePtr;    /* Return - sizeof(Fsio_FileState) */
  633.     Address    *dataPtr;    /* Return - pointer to Fsio_FileState */
  634. {
  635.     register ReturnStatus        status;
  636.     register Fsio_FileState        *fileStatePtr;
  637.  
  638.     if (migInfoPtr->ioFileID.serverID == rpc_SpriteID) {
  639.     /*
  640.      * The file was remote, which is why we were called, but is now local.
  641.      */
  642.     migInfoPtr->ioFileID.type = FSIO_LCL_FILE_STREAM;
  643.     return(Fsio_FileMigrate(migInfoPtr, dstClientID, flagsPtr, offsetPtr,
  644.                 sizePtr, dataPtr));
  645.     }
  646.     migInfoPtr->ioFileID.type = FSIO_RMT_FILE_STREAM;
  647.     fileStatePtr = mnew(Fsio_FileState);
  648.     status = Fsrmt_NotifyOfMigration(migInfoPtr, flagsPtr, offsetPtr,
  649.         sizeof(Fsio_FileState), (Address)fileStatePtr);
  650.     if (status != SUCCESS) {
  651.     printf( "FsrmtFileMigrate, server error <%x>\n",
  652.         status);
  653.     } else {
  654.     *dataPtr = (Address)fileStatePtr;
  655.     *sizePtr = sizeof(Fsio_FileState);
  656.     }
  657.     return(status);
  658. }
  659.  
  660.  
  661. /*
  662.  *----------------------------------------------------------------------
  663.  *
  664.  * FsrmtFileRead --
  665.  *
  666.  *    Read from a remote file.  This tries the cache first, and then
  667.  *    goes remote if the file is not cacheable.  This also checks against
  668.  *    remotely shared streams (due to migration), and bypasses the cache
  669.  *    in that case.
  670.  *
  671.  * Results:
  672.  *    The results of Fscache_Read, or of the RPC.
  673.  *
  674.  * Side effects:
  675.  *    The *offsetPtr is updated to reflect the read.
  676.  *
  677.  *----------------------------------------------------------------------
  678.  */
  679. ReturnStatus
  680. FsrmtFileRead(streamPtr, readPtr, remoteWaitPtr, replyPtr)
  681.     Fs_Stream        *streamPtr;    /* Stream to a remote file. */
  682.     Fs_IOParam        *readPtr;    /* Read parameter block. */
  683.     Sync_RemoteWaiter    *remoteWaitPtr;    /* Process info for remote waiting */
  684.     Fs_IOReply        *replyPtr;    /* Signal to return, if any,
  685.                      * plus the amount read. */
  686. {
  687.     register Fsrmt_FileIOHandle *handlePtr =
  688.         (Fsrmt_FileIOHandle *)streamPtr->ioHandlePtr;
  689.     register ReturnStatus status;
  690. #ifdef SOSP91
  691.     Boolean        isForeign = FALSE;    /* Due to migration? */
  692.     Boolean        isDir = FALSE;        /* It's a directory? */
  693. #endif SOSP91
  694.  
  695.     if (readPtr->flags & FS_RMT_SHARED) {
  696.     /*
  697.      * The stream is shared accross the network.  We have to go through
  698.      * to the file server to get the correct stream offset.
  699.      */
  700.     status = FS_NOT_CACHEABLE;
  701.     } else {
  702.     status = Fscache_Read(&handlePtr->cacheInfo, readPtr->flags,
  703.             readPtr->buffer, readPtr->offset, &readPtr->length,
  704.             remoteWaitPtr);
  705.     replyPtr->length = readPtr->length;
  706.     }
  707.     /*
  708.      * If not-cacheable then go to the remote file server.  Otherwise
  709.      * update the amount read in the reply because Fscache_Read uses
  710.      * the old-style in/out length variable.
  711.      */
  712.     if (status != FS_NOT_CACHEABLE) {
  713.     replyPtr->length = readPtr->length;
  714.     } else {
  715. #ifdef SOSP91
  716.     if (handlePtr->cacheInfo.flags & FSCACHE_IS_DIR) {
  717.         isDir = TRUE;
  718.     }
  719. #endif /* SOSP91 */
  720.     status = Fsrmt_Read(streamPtr, readPtr, remoteWaitPtr, replyPtr);
  721.     if (status == SUCCESS) {
  722. #ifdef SOSP91
  723.         if (proc_RunningProcesses[0] != (Proc_ControlBlock *) NIL) {
  724.             if ((proc_RunningProcesses[0]->state == PROC_MIGRATED) ||
  725.                 (proc_RunningProcesses[0]->genFlags &
  726.                 (PROC_FOREIGN | PROC_MIGRATING))) {
  727.             isForeign = TRUE;
  728.             }
  729.         }
  730. #endif SOSP91
  731.         if (readPtr->flags & FS_RMT_SHARED) {
  732.         fs_Stats.rmtIO.sharedStreamBytesRead += replyPtr->length;
  733. #ifdef SOSP91
  734.         if (isForeign) {
  735.             fs_SospMigStats.rmtIO.sharedStreamBytesRead +=
  736.                 replyPtr->length;
  737.         }
  738. #endif SOSP91
  739.         } else {
  740.         fs_Stats.rmtIO.uncacheableBytesRead += replyPtr->length;
  741. #ifdef SOSP91
  742.         if (isForeign) {
  743.             fs_SospMigStats.rmtIO.uncacheableBytesRead +=
  744.                 replyPtr->length;
  745.         }
  746.         if (isDir) {
  747.             fs_MoreStats.uncacheableDirBytesRead += replyPtr->length;
  748.             if (isForeign) {
  749.             fs_MoreStats.uncacheableDirBytesReadMig +=
  750.                 replyPtr->length;
  751.             }
  752.         }
  753. #endif SOSP91
  754.         }
  755.     }
  756.     }
  757.     return(status);
  758. }
  759.  
  760. /*
  761.  *----------------------------------------------------------------------
  762.  *
  763.  * FsrmtFileWrite --
  764.  *
  765.  *    Write to a remote file.  This checks for cachability and uses
  766.  *    either the cache write routine or an RPC stub.
  767.  *
  768.  * Results:
  769.  *    The results of Fscache_Write or the RPC.
  770.  *
  771.  * Side effects:
  772.  *    A buffer may have to allocated when doing an uncached write.
  773.  *
  774.  *----------------------------------------------------------------------
  775.  */
  776. ReturnStatus
  777. FsrmtFileWrite(streamPtr, writePtr, remoteWaitPtr, replyPtr)
  778.     Fs_Stream        *streamPtr;    /* Open stream to remote file. */
  779.     Fs_IOParam        *writePtr;    /* Read parameter block */
  780.     Sync_RemoteWaiter    *remoteWaitPtr;    /* Process info for remote waiting */
  781.     Fs_IOReply        *replyPtr;    /* Signal to return, if any */
  782. {
  783.     register Fsrmt_FileIOHandle *handlePtr =
  784.         (Fsrmt_FileIOHandle *)streamPtr->ioHandlePtr;
  785.     register ReturnStatus status;
  786. #ifdef SOSP91
  787.     Boolean        isForeign = FALSE;    /* Due to migration? */
  788. #endif SOSP91
  789.  
  790.     if (writePtr->flags & FS_RMT_SHARED) {
  791.     status = FS_NOT_CACHEABLE;
  792.     } else {
  793.     Fscache_WaitForReadAhead(&handlePtr->readAhead);
  794.     status = Fscache_Write(&handlePtr->cacheInfo, writePtr->flags,
  795.                   writePtr->buffer, writePtr->offset,
  796.                       &writePtr->length, remoteWaitPtr);
  797.     writePtr->flags &= ~FS_SERVER_WRITE_THRU;
  798.     Fscache_AllowReadAhead(&handlePtr->readAhead);
  799.     }
  800.     if (status != FS_NOT_CACHEABLE) {
  801.     replyPtr->length = writePtr->length;
  802.     } else {
  803.     status = Fsrmt_Write(streamPtr, writePtr, remoteWaitPtr, replyPtr);
  804.     if (status == SUCCESS) {
  805. #ifdef SOSP91
  806.         if (proc_RunningProcesses[0] != (Proc_ControlBlock *) NIL) {
  807.         if ((proc_RunningProcesses[0]->state == PROC_MIGRATED) ||
  808.             (proc_RunningProcesses[0]->genFlags &
  809.             (PROC_FOREIGN | PROC_MIGRATING))) {
  810.             isForeign = TRUE;
  811.         }
  812.         }
  813. #endif SOSP91
  814.         if (writePtr->flags & FS_RMT_SHARED) {
  815.         fs_Stats.rmtIO.sharedStreamBytesWritten += replyPtr->length;
  816. #ifdef SOSP91
  817.         if (isForeign) {
  818.             fs_SospMigStats.rmtIO.sharedStreamBytesWritten++;
  819.         }
  820. #endif SOSP91
  821.         } else {
  822.         fs_Stats.rmtIO.uncacheableBytesWritten += replyPtr->length;
  823. #ifdef SOSP91
  824.         if (isForeign) {
  825.             fs_SospMigStats.rmtIO.uncacheableBytesWritten++;
  826.         }
  827. #endif SOSP91
  828.         }
  829.     }
  830.     }
  831.     return(status);
  832. }
  833.  
  834. /*
  835.  *----------------------------------------------------------------------
  836.  *
  837.  * FsrmtFilePageRead --
  838.  *
  839.  *    Do a page-in for a remote file.
  840.  *
  841.  * Results:
  842.  *    The results of Fscache_Read, or of Fsrmt_Read.
  843.  *
  844.  * Side effects:
  845.  *    None.
  846.  *
  847.  *----------------------------------------------------------------------
  848.  */
  849. ReturnStatus
  850. FsrmtFilePageRead(streamPtr, readPtr, remoteWaitPtr, replyPtr)
  851.     Fs_Stream        *streamPtr;    /* Stream to a remote file. */
  852.     Fs_IOParam        *readPtr;    /* Read parameter block. */
  853.     Sync_RemoteWaiter    *remoteWaitPtr;    /* Process info for remote waiting */
  854.     Fs_IOReply        *replyPtr;    /* Signal to return, if any,
  855.                      * plus the amount read. */
  856. {
  857.     register Fsrmt_FileIOHandle *handlePtr =
  858.         (Fsrmt_FileIOHandle *)streamPtr->ioHandlePtr;
  859.     register ReturnStatus status = SUCCESS;
  860.     int savedOffset = readPtr->offset;
  861.     int savedLength = readPtr->length;
  862.     Address savedBuffer = readPtr->buffer;
  863. #ifdef SOSP91
  864.     Boolean        isForeign = FALSE;    /* Due to migration? */
  865. #endif SOSP91
  866.  
  867. #ifdef SOSP91
  868.     if (proc_RunningProcesses[0] != (Proc_ControlBlock *) NIL) {
  869.     if ((proc_RunningProcesses[0]->state == PROC_MIGRATED) ||
  870.         (proc_RunningProcesses[0]->genFlags &
  871.         (PROC_FOREIGN | PROC_MIGRATING))) {
  872.         isForeign = TRUE;
  873.     }
  874.     }
  875. #endif SOSP91
  876.     /*
  877.      * This should check if the file is cached if:
  878.      * a) it is not a FS_SWAP file or
  879.      * b) it is a shared file (which will be FS_SWAP)
  880.      * but for now we'll just always check.  - Ken
  881.      */
  882.     if (1 || (readPtr->flags & FS_SWAP) == 0) {
  883.     int blockNum, firstBlock, lastBlock, size, toRead;
  884.     Fscache_Block *blockPtr;
  885.     Boolean found;
  886.     /*
  887.      * This is either a CODE or HEAP page, so we check in our cache
  888.      * to see if we have it there;  we may have just written it.
  889.      * We are now, once again, attempting to special-case HEAP pages.
  890.      * We want to keep the clean copies in the cache so they can
  891.      * be re-read.
  892.      */
  893.     size = readPtr->length;
  894.     firstBlock = (unsigned int) readPtr->offset / FS_BLOCK_SIZE;
  895.     lastBlock = (unsigned int) (readPtr->offset + size - 1) /
  896.             FS_BLOCK_SIZE;
  897.     for (blockNum = firstBlock;
  898.          blockNum <= lastBlock; blockNum++) {
  899.         toRead = size;
  900.         if ((unsigned int) (readPtr->offset + size - 1)
  901.             / FS_BLOCK_SIZE > blockNum) {
  902.         toRead = (blockNum + 1) * FS_BLOCK_SIZE - readPtr->offset;
  903.         }
  904.         /*
  905.          * NOTE:  After SOSP stats are taken, fix the bytesRead counter
  906.          * to include bytes fetched for VM from this Fscache_FetchBlock
  907.          * call.  Update readAccesses, readHits and readMisses accordingly.
  908.          * To see how to do this, look at how the counters are updated
  909.          * in Fscache_Read after the call to Fscache_FetchBlock.  We can't
  910.          * do this before the SOSP stats are done, since the postprocessors
  911.          * already know to adjust for this problem.
  912.          */
  913.         Fscache_FetchBlock(&handlePtr->cacheInfo, blockNum,
  914.             FSCACHE_DATA_BLOCK, &blockPtr, &found);
  915.         if (found) {
  916.         fs_Stats.rmtIO.hitsOnVMBlock++;
  917. #ifdef SOSP91
  918.         if (isForeign) {
  919.             fs_SospMigStats.rmtIO.hitsOnVMBlock++;
  920.         }
  921. #endif SOSP91
  922.         bcopy(blockPtr->blockAddr + (readPtr->offset &
  923.             FS_BLOCK_OFFSET_MASK), readPtr->buffer, toRead);
  924.         if (blockPtr->flags & FSCACHE_READ_AHEAD_BLOCK) {
  925.             fs_Stats.blockCache.readAheadHits++;
  926. #ifdef SOSP91
  927.             if (isForeign) {
  928.             fs_SospMigStats.blockCache.readAheadHits++;
  929.             }
  930. #endif SOSP91
  931.         }
  932.         /*
  933.          * Let heap pages sit in the cache.
  934.          */
  935.         if (readPtr->flags & FS_HEAP) {
  936.             fs_Stats.rmtIO.hitsOnHeapBlock++;
  937. #ifdef SOSP91
  938.             if (isForeign) {
  939.             fs_SospMigStats.rmtIO.hitsOnHeapBlock++;
  940.             }
  941. #endif SOSP91
  942.             Fscache_UnlockBlock(blockPtr, 0, -1, 0,
  943.                 FSCACHE_CLEAR_READ_AHEAD);
  944.         } else {
  945. #ifdef SOSP91
  946.             if (readPtr->flags & FS_SWAP) {
  947.             fs_MoreStats.hitsOnSwapPage++;
  948.             if (isForeign) {
  949.                 fs_MoreStats.hitsOnSwapPageM++;
  950.             }
  951.             } else if ((readPtr->flags & (FS_HEAP | FS_SWAP)) == 0) {
  952.             /* It's a code page */
  953.             fs_MoreStats.hitsOnCodePage++;
  954.             if (isForeign) {
  955.                 fs_MoreStats.hitsOnCodePageM++;
  956.             }
  957.             }
  958. #endif SOSP91
  959.             Fscache_UnlockBlock(blockPtr, 0, -1, 0,
  960.                 FSCACHE_CLEAR_READ_AHEAD | FSCACHE_BLOCK_UNNEEDED);
  961.         }
  962.         } else {
  963.         fs_Stats.rmtIO.missesOnVMBlock++;
  964. #ifdef SOSP91
  965.         if (isForeign) {
  966.             fs_SospMigStats.rmtIO.missesOnVMBlock++;
  967.         }
  968. #endif SOSP91
  969.         /*
  970.          * It's an initialized heap page.  Read it into the
  971.          * cache.
  972.          */
  973.         if ((readPtr->flags & FS_HEAP) &&
  974.             blockPtr != (Fscache_Block *) NIL) {
  975.             Fscache_FileInfo    *cacheInfoPtr;
  976.  
  977.             fs_Stats.rmtIO.missesOnHeapBlock++;
  978. #ifdef SOSP91
  979.             if (isForeign) {
  980.             fs_SospMigStats.rmtIO.missesOnHeapBlock++;
  981.             }
  982. #endif /* SOSP91 */
  983.             cacheInfoPtr = &handlePtr->cacheInfo;
  984.             status = (cacheInfoPtr->backendPtr->ioProcs.blockRead)
  985.                 (cacheInfoPtr->hdrPtr, blockPtr, remoteWaitPtr);
  986.             if (status == SUCCESS) {
  987.             /* Copy to vm block */
  988.             bcopy(blockPtr->blockAddr + (readPtr->offset &
  989.                 FS_BLOCK_OFFSET_MASK), readPtr->buffer, toRead);
  990.             fs_Stats.rmtIO.bytesReadForVM += toRead;
  991.             fs_Stats.rmtIO.bytesReadForHeap += toRead;
  992. #ifdef SOSP91
  993.             if (isForeign) {
  994.                 fs_SospMigStats.rmtIO.bytesReadForVM += toRead;
  995.                 fs_SospMigStats.rmtIO.bytesReadForHeap += toRead;
  996.             }
  997. #endif SOSP91
  998.             Fscache_UnlockBlock(blockPtr, 0, -1, 0,
  999.                 FSCACHE_CLEAR_READ_AHEAD);
  1000.             }
  1001.         }
  1002.         if (status != SUCCESS || !(readPtr->flags & FS_HEAP) ||
  1003.             blockPtr == (Fscache_Block *) NIL) {
  1004.             if (blockPtr != (Fscache_Block *)NIL) {
  1005.             Fscache_UnlockBlock(blockPtr, 0, -1, 0,
  1006.                 FSCACHE_DELETE_BLOCK);
  1007.             }
  1008. #ifdef SOSP91
  1009.             if (readPtr->flags & FS_SWAP) {
  1010.             fs_MoreStats.missesOnSwapPage++;
  1011.             if (isForeign) {
  1012.                 fs_MoreStats.missesOnSwapPageM++;
  1013.             }
  1014.             } else if ((readPtr->flags & (FS_HEAP | FS_SWAP)) == 0) {
  1015.             /* It's a code page. */
  1016.             fs_MoreStats.missesOnCodePage++;
  1017.             if (isForeign) {
  1018.                 fs_MoreStats.missesOnCodePageM++;
  1019.             }
  1020.             }
  1021. #endif SOSP91
  1022.  
  1023.             readPtr->length = toRead;
  1024.             status = Fsrmt_Read(streamPtr, readPtr, remoteWaitPtr, replyPtr);
  1025.             if (status != SUCCESS) {
  1026.             break;
  1027.             }
  1028.             fs_Stats.rmtIO.bytesReadForVM += toRead;
  1029.             if (readPtr->flags & FS_HEAP) {
  1030.             fs_Stats.rmtIO.bytesReadForHeapUncached += toRead;
  1031.             }
  1032. #ifdef SOSP91
  1033.             if (isForeign) {
  1034.             fs_SospMigStats.rmtIO.bytesReadForVM += toRead;
  1035.             if (readPtr->flags & FS_HEAP) {
  1036.                 fs_SospMigStats.rmtIO.bytesReadForHeapUncached +=
  1037.                     toRead;
  1038.             }
  1039.             }
  1040. #endif SOSP91
  1041.         }
  1042.         }
  1043.         /*
  1044.          * Successfully read one FS block, either remotely or from
  1045.          * the cache.  Update pointers and loop.
  1046.          */
  1047.         size -= toRead;
  1048.         readPtr->offset += toRead;
  1049.         readPtr->buffer += toRead;
  1050.     }
  1051.     } else {
  1052.     /*
  1053.      * Page-in of non-cacheable data (swap file).
  1054.      */
  1055.     status = Fsrmt_Read(streamPtr, readPtr, remoteWaitPtr, replyPtr);
  1056.     if (status == SUCCESS) {
  1057.         fs_Stats.rmtIO.bytesReadForVM += replyPtr->length;
  1058. #ifdef SOSP91
  1059.         if (isForeign) {
  1060.         fs_SospMigStats.rmtIO.bytesReadForVM += replyPtr->length;
  1061.         }
  1062. #endif SOSP91
  1063.     }
  1064.     }
  1065.     if (status != SUCCESS) {
  1066.     readPtr->offset = savedOffset;
  1067.     readPtr->length = savedLength;
  1068.     readPtr->buffer = savedBuffer;
  1069.     }
  1070.     return(status);
  1071. }
  1072.  
  1073. /*
  1074.  *----------------------------------------------------------------------
  1075.  *
  1076.  * FsrmtFilePageWrite --
  1077.  *
  1078.  *    Do a page-out for a remote file.
  1079.  *    NB: this knows that remote block allocation is a no-op, so
  1080.  *    there is no call to the allocation routine.
  1081.  *
  1082.  * Results:
  1083.  *    The results of Fsrmt_Write.
  1084.  *
  1085.  * Side effects:
  1086.  *    Statistics are taken.  (This could be replaced with Fsrmt_Write
  1087.  *    if these statistics aren't needed.)
  1088.  *
  1089.  *----------------------------------------------------------------------
  1090.  */
  1091. ReturnStatus
  1092. FsrmtFilePageWrite(streamPtr, writePtr, remoteWaitPtr, replyPtr)
  1093.     Fs_Stream        *streamPtr;    /* Open stream to remote file. */
  1094.     Fs_IOParam        *writePtr;    /* Read parameter block */
  1095.     Sync_RemoteWaiter    *remoteWaitPtr;    /* Process info for remote waiting */
  1096.     Fs_IOReply        *replyPtr;    /* Signal to return, if any */
  1097. {
  1098.     ReturnStatus status;
  1099. #ifdef SOSP91
  1100.     Boolean        isForeign = FALSE;    /* Due to migration? */
  1101. #endif SOSP91
  1102.  
  1103.     status = Fsrmt_Write(streamPtr, writePtr, remoteWaitPtr, replyPtr);
  1104.     if (status == SUCCESS) {
  1105. #ifdef SOSP91
  1106.     if (proc_RunningProcesses[0] != (Proc_ControlBlock *) NIL) {
  1107.         if ((proc_RunningProcesses[0]->state == PROC_MIGRATED) ||
  1108.             (proc_RunningProcesses[0]->genFlags &
  1109.             (PROC_FOREIGN | PROC_MIGRATING))) {
  1110.         isForeign = TRUE;
  1111.         }
  1112.     }
  1113. #endif SOSP91
  1114.     fs_Stats.rmtIO.bytesWrittenForVM += replyPtr->length;
  1115. #ifdef SOSP91
  1116.     if (isForeign) {
  1117.         fs_SospMigStats.rmtIO.bytesWrittenForVM += replyPtr->length;
  1118.     }
  1119. #endif SOSP91
  1120.     }
  1121.     return(status);
  1122. }
  1123.  
  1124. /*
  1125.  *----------------------------------------------------------------------
  1126.  *
  1127.  * FsrmtFileBlockRead --
  1128.  *
  1129.  *    Read in a cache block for a remote file.
  1130.  *
  1131.  * Results:
  1132.  *    The return code from the server.
  1133.  *
  1134.  * Side effects:
  1135.  *    This sets the blockPtr->blockSize to be the actual amount of
  1136.  *    data read into the block.  Any left over space is zero filled.
  1137.  *
  1138.  *----------------------------------------------------------------------
  1139.  */
  1140. static ReturnStatus
  1141. FsrmtFileBlockRead(hdrPtr, blockPtr, waitPtr)
  1142.     Fs_HandleHeader *hdrPtr;    /* Pointer to handle for file to write to. */
  1143.     Fscache_Block *blockPtr;    /* Block to read in.  blockNum is the logical
  1144.                  * block and indicates the offset.  blockSize
  1145.                  * is set to FS_BLOCK_SIZE, but we reduce
  1146.                  * that if less gets read.  blockAddr is
  1147.                  * the memory area for the block. */
  1148.     Sync_RemoteWaiter *waitPtr;    /* For remote waiting if remote cache is full */
  1149. {
  1150.     Fs_Stream        dummyStream;
  1151.     Fs_IOParam        io;
  1152.     Fs_IOReply        reply;
  1153.     ReturnStatus    status;
  1154. #ifdef SOSP91
  1155.     Boolean        isForeign = FALSE;    /* Due to migration? */
  1156. #endif SOSP91
  1157.  
  1158.     dummyStream.hdr.fileID.type = -1;
  1159.     dummyStream.ioHandlePtr = hdrPtr;
  1160. #ifdef SOSP91
  1161.     if (proc_RunningProcesses[0] != (Proc_ControlBlock *) NIL) {
  1162.     if ((proc_RunningProcesses[0]->state == PROC_MIGRATED) ||
  1163.         (proc_RunningProcesses[0]->genFlags &
  1164.         (PROC_FOREIGN | PROC_MIGRATING))) {
  1165.         isForeign = TRUE;
  1166.     }
  1167.     }
  1168. #endif SOSP91
  1169.  
  1170.     io.buffer = blockPtr->blockAddr;
  1171.     io.length = FS_BLOCK_SIZE;
  1172.     io.offset = blockPtr->blockNum * FS_BLOCK_SIZE;
  1173.     io.flags = 0;
  1174.  
  1175.     status = Fsrmt_Read(&dummyStream, &io, waitPtr, &reply);
  1176.     blockPtr->blockSize = reply.length;
  1177.     if (blockPtr->blockSize < FS_BLOCK_SIZE) {
  1178.     /*
  1179.      * We always must make sure that every cache block is filled
  1180.      * with zeroes.  Since we didn't read a full block zero fill
  1181.      * the rest.
  1182.      */
  1183.     fs_Stats.blockCache.readZeroFills++;
  1184.     bzero(blockPtr->blockAddr + blockPtr->blockSize,
  1185.         FS_BLOCK_SIZE - blockPtr->blockSize);
  1186.     }
  1187.     fs_Stats.rmtIO.bytesReadForCache += blockPtr->blockSize;
  1188. #ifdef SOSP91
  1189.     if (isForeign) {
  1190.     fs_SospMigStats.rmtIO.bytesReadForCache += blockPtr->blockSize;
  1191.     }
  1192. #endif SOSP91
  1193.     return(status);
  1194. }
  1195.  
  1196. /*
  1197.  *----------------------------------------------------------------------
  1198.  *
  1199.  * FsrmtFileBlockWrite --
  1200.  *
  1201.  *    Write out a cache block for a remote file.  This understands
  1202.  *    that the diskBlock is the same as the (logical) blockNum
  1203.  *    of the block.  It marks the write as coming from a client cache
  1204.  *    so the server doesn't update the modify time of the file.
  1205.  *
  1206.  *
  1207.  * Results:
  1208.  *    The return code from the RPC.
  1209.  *
  1210.  * Side effects:
  1211.  *    The write.
  1212.  *
  1213.  *----------------------------------------------------------------------
  1214.  */
  1215. static ReturnStatus
  1216. FsrmtFileBlockWrite(hdrPtr, blockPtr, flags)
  1217.     Fs_HandleHeader *hdrPtr;    /* I/O handle of file to write. */
  1218.     Fscache_Block *blockPtr;    /* The cache block to write. */
  1219.     int        flags;
  1220. {
  1221.     ReturnStatus    status;
  1222.     Fs_Stream        dummyStream;
  1223.     Fs_IOParam        io;
  1224.     Fs_IOReply        reply;
  1225. #ifdef SOSP91
  1226.     Boolean        isForeign = FALSE;    /* Due to migration? */
  1227. #endif SOSP91
  1228.  
  1229.     /*
  1230.      *    The server recognizes the write RPC as coming from the
  1231.      *    cache (FS_CLIENT_CACHE_WRITE) and ignores the streamID.
  1232.      */
  1233.     dummyStream.hdr.fileID.type = -1;
  1234.     dummyStream.ioHandlePtr = hdrPtr;
  1235.  
  1236.     io.buffer = blockPtr->blockAddr;
  1237.     io.length = blockPtr->blockSize;
  1238.     io.offset = blockPtr->diskBlock * FS_BLOCK_SIZE; /* diskBlock == blockNum */
  1239.     io.flags = flags | FS_CLIENT_CACHE_WRITE;
  1240.  
  1241.     status = Fsrmt_Write(&dummyStream, &io, (Sync_RemoteWaiter *)NIL, &reply);
  1242.     if (status == SUCCESS) {
  1243. #ifdef SOSP91
  1244.     if (proc_RunningProcesses[0] != (Proc_ControlBlock *) NIL) {
  1245.         if ((proc_RunningProcesses[0]->state == PROC_MIGRATED) ||
  1246.             (proc_RunningProcesses[0]->genFlags &
  1247.             (PROC_FOREIGN | PROC_MIGRATING))) {
  1248.         isForeign = TRUE;
  1249.         }
  1250.     }
  1251. #endif SOSP91
  1252.     fs_Stats.rmtIO.bytesWrittenFromCache += blockPtr->blockSize;
  1253. #ifdef SOSP91
  1254.     if (isForeign) {
  1255.         fs_SospMigStats.rmtIO.bytesWrittenFromCache += blockPtr->blockSize;
  1256.     }
  1257. #endif SOSP91
  1258.     }
  1259.     return(status);
  1260. }
  1261.  
  1262. /*
  1263.  *----------------------------------------------------------------------
  1264.  *
  1265.  * FsrmtFileBlockAllocate --
  1266.  *
  1267.  *    Allocate disk space for a remote file.  This always works, ie.
  1268.  *    the server is not contacted.  The offset is just mapped to a
  1269.  *    logical block number for the file.
  1270.  *
  1271.  *    IF THIS IS CHANGED TO ACTUALLY DO SOMETHING, then please add
  1272.  *    a call to this routine in FsrmtFilePageWrite.
  1273.  *
  1274.  * Results:
  1275.  *    None.
  1276.  *
  1277.  * Side effects:
  1278.  *    None.
  1279.  *
  1280.  *----------------------------------------------------------------------
  1281.  */
  1282. /*ARGSUSED*/
  1283. static ReturnStatus
  1284. FsrmtFileBlockAllocate(hdrPtr, offset, numBytes, flags, blockAddrPtr, newBlockPtr)
  1285.     Fs_HandleHeader    *hdrPtr;    /* Local file handle. */
  1286.     int         offset;        /* Offset to allocate at. */
  1287.     int         numBytes;    /* Number of bytes to allocate. */
  1288.     int            flags;        /* FSCACHE_DONT_BLOCK */
  1289.     int            *blockAddrPtr;     /* Disk address of block allocated. */
  1290.     Boolean        *newBlockPtr;    /* TRUE if there was no block allocated
  1291.                      * before. */
  1292. {
  1293.     *newBlockPtr = FALSE;
  1294.     *blockAddrPtr = offset / FS_BLOCK_SIZE;
  1295.     return(SUCCESS);
  1296. }
  1297.  
  1298. /*
  1299.  *----------------------------------------------------------------------
  1300.  *
  1301.  * FsrmtFileTrunc --
  1302.  *
  1303.  *    Truncate a remote file. Nothing need be done is the remote case
  1304.  *    since all the work is done on the file server.
  1305.  *
  1306.  * Results:
  1307.  *    SUCCESS
  1308.  *
  1309.  * Side effects:
  1310.  *
  1311.  *----------------------------------------------------------------------
  1312.  */
  1313. /*ARGSUSED*/
  1314. static ReturnStatus
  1315. FsrmtFileTrunc(hdrPtr, size, delete)
  1316.     Fs_HandleHeader *hdrPtr;    /* I/O handle for the file. */
  1317.     int            size;    /* Size to truncate to. */
  1318.     Boolean        delete;    /* True if the file is being deleted. */
  1319. {
  1320.     return SUCCESS;
  1321. }
  1322.  
  1323. /*
  1324.  *----------------------------------------------------------------------
  1325.  *
  1326.  * FsrmtFileIOControl --
  1327.  *
  1328.  *    IOControls for remote regular files.  Note, no byte order
  1329.  *    checking/fixing is down here as this is always called directly from
  1330.  *    a process, never via RPC.
  1331.  *
  1332.  * Results:
  1333.  *    An error code from the command.
  1334.  *
  1335.  * Side effects:
  1336.  *    Command dependent.
  1337.  *
  1338.  *----------------------------------------------------------------------
  1339.  */
  1340.  
  1341. /*ARGSUSED*/
  1342. ReturnStatus
  1343. FsrmtFileIOControl(streamPtr, ioctlPtr, replyPtr)
  1344.     Fs_Stream *streamPtr;        /* Stream to remote file */
  1345.     Fs_IOCParam *ioctlPtr;        /* I/O Control parameter block */
  1346.     Fs_IOReply *replyPtr;        /* Return length and signal */
  1347. {
  1348.     register Fsrmt_FileIOHandle *handlePtr =
  1349.         (Fsrmt_FileIOHandle *)streamPtr->ioHandlePtr;
  1350.     register ReturnStatus status;
  1351.  
  1352.     Fsutil_HandleLock(handlePtr);
  1353.     switch(ioctlPtr->command) {
  1354.     case IOC_REPOSITION: {
  1355. #ifdef SOSP91
  1356.         Ioc_RepositionArgs *iocArgsPtr;
  1357.         iocArgsPtr = (Ioc_RepositionArgs *) ioctlPtr->inBuffer;
  1358.         /*
  1359.          * Only send an RPC if the stream is remote shared, or
  1360.          * if the lseek is to somewhere other than the current location
  1361.          * since we don't want to trace lseeks to the same place.
  1362.          */
  1363.         if ((streamPtr->flags & FS_RMT_SHARED) ||
  1364.         (iocArgsPtr->base != IOC_BASE_CURRENT) ||
  1365.         (iocArgsPtr->offset != 0)) {
  1366. #else
  1367.         if (streamPtr->flags & FS_RMT_SHARED) {
  1368. #endif
  1369.         status = Fsrmt_IOControl(streamPtr, ioctlPtr, replyPtr);
  1370. #ifdef SOSP91
  1371.         status = SUCCESS;
  1372. #endif
  1373.         } else {
  1374.         status = SUCCESS;
  1375.         }
  1376.         break;
  1377.     }
  1378.     case IOC_GET_FLAGS:
  1379.         if (ioctlPtr->outBufSize >= sizeof(int)) {
  1380.         *(int *)ioctlPtr->outBuffer = 0;
  1381.         }
  1382.         status = SUCCESS;
  1383.         break;
  1384.     case IOC_SET_FLAGS:
  1385.     case IOC_SET_BITS:
  1386.     case IOC_CLEAR_BITS:
  1387.         status = SUCCESS;
  1388.         break;
  1389.     case IOC_TRUNCATE:
  1390.         if (ioctlPtr->inBufSize >= sizeof(int)) {
  1391.         register int length = *(int *)ioctlPtr->inBuffer;
  1392.         Fscache_Trunc(&handlePtr->cacheInfo, length, 0);
  1393.         status = Fsrmt_IOControl(streamPtr, ioctlPtr, replyPtr);
  1394.         } else {
  1395.         status = GEN_INVALID_ARG;
  1396.         }
  1397.         break;
  1398.     case IOC_MAP:
  1399.         if (ioctlPtr->inBufSize >= sizeof(int)) {
  1400.         status = Fsrmt_IOControl(streamPtr, ioctlPtr, replyPtr);
  1401.         } else {
  1402.         status = GEN_INVALID_ARG;
  1403.         }
  1404.         break;
  1405.     case IOC_LOCK:
  1406.     case IOC_UNLOCK:
  1407.         status = Fsrmt_IOControl(streamPtr, ioctlPtr, replyPtr);
  1408.         break;
  1409.     case IOC_NUM_READABLE: {
  1410.         register int bytesAvailable;
  1411.         register int streamOffset;
  1412.  
  1413.         if (ioctlPtr->outBufSize < sizeof(int)) {
  1414.         return(GEN_INVALID_ARG);
  1415.         }
  1416.         streamOffset = *(int *)ioctlPtr->inBuffer;
  1417.         bytesAvailable = handlePtr->cacheInfo.attr.lastByte + 1 -
  1418.                 streamOffset;
  1419.         *(int *)ioctlPtr->outBuffer = bytesAvailable;
  1420.         status = SUCCESS;
  1421.         break;
  1422.     }
  1423.     case IOC_SET_OWNER:
  1424.     case IOC_GET_OWNER:
  1425.         status = GEN_NOT_IMPLEMENTED;
  1426.         break;
  1427.     case IOC_PREFIX:
  1428.         status = SUCCESS;
  1429.         break;
  1430.     case IOC_WRITE_BACK: {
  1431.         /*
  1432.          * Write out the cached data for the file.
  1433.          */
  1434.         Ioc_WriteBackArgs *argPtr = (Ioc_WriteBackArgs *)ioctlPtr->inBuffer;
  1435.         Fscache_FileInfo *cacheInfoPtr = &handlePtr->cacheInfo;
  1436.  
  1437.         if (ioctlPtr->inBufSize < sizeof(Ioc_WriteBackArgs)) {
  1438.         status = GEN_INVALID_ARG;
  1439.         } else {
  1440.         int firstBlock, lastBlock;
  1441.         int blocksSkipped;
  1442.         int flags = 0;
  1443.         if (argPtr->shouldBlock) {
  1444.             flags |= FSCACHE_FILE_WB_WAIT;
  1445.         }
  1446.         if (argPtr->firstByte > 0) {
  1447.             firstBlock = argPtr->firstByte / FS_BLOCK_SIZE;
  1448.         } else {
  1449.             firstBlock = 0;
  1450.         }
  1451.         if (argPtr->lastByte > 0) {
  1452.             lastBlock = argPtr->lastByte / FS_BLOCK_SIZE;
  1453.         } else {
  1454.             lastBlock = FSCACHE_LAST_BLOCK;
  1455.         }
  1456. #ifdef SOSP91
  1457.         cacheInfoPtr->flags |= FSCACHE_SYNC;
  1458. #endif SOSP91
  1459.         status = Fscache_FileWriteBack(cacheInfoPtr, firstBlock,
  1460.             lastBlock, flags, &blocksSkipped);
  1461.         if (status == SUCCESS) {
  1462.             /*
  1463.              * Perform the IOC_WRITE_BACK on the file server to 
  1464.              * insure that the file is forced to disk.
  1465.              */
  1466.             status = Fsrmt_IOControl(streamPtr, ioctlPtr, replyPtr);
  1467. #define FILE_SERVER_IOC_WRITE_BACK_BROKEN
  1468. #ifdef FILE_SERVER_IOC_WRITE_BACK_BROKEN
  1469.             if (status == GEN_INVALID_ARG) {
  1470.             /*
  1471.              * Currently, IOC_WRITE_BACK don't work to machines
  1472.              * with different byte orders. This has been fixed
  1473.              * but until all file servers run the kernel we
  1474.              * patch round the bug. 
  1475.              * THIS CODE CAN BE REMOVED when all file servers
  1476.              * are running a version > 1.075.
  1477.              */
  1478.             status = SUCCESS;
  1479.             }
  1480. #endif /* FILE_SERVER_IOC_WRITE_BACK_BROKEN */
  1481.         }
  1482.  
  1483.         }
  1484.         break;
  1485.     }
  1486.     default:
  1487.         status = GEN_INVALID_ARG;
  1488.         break;
  1489.     }
  1490.     Fsutil_HandleUnlock(handlePtr);
  1491.     return(status);
  1492. }
  1493.  
  1494. /*
  1495.  *----------------------------------------------------------------------
  1496.  *
  1497.  * FsrmtFileGetIOAttr --
  1498.  *
  1499.  *    Update the attributes of a remotely served file from attributes
  1500.  *    that we have cached here.  The file server will have contacted
  1501.  *    other clients that may be caching the file, but we still need
  1502.  *    to check our own version of the access/modify times that we
  1503.  *    (might) have cached.
  1504.  *
  1505.  * Results:
  1506.  *    SUCCESS        - always returned.
  1507.  *
  1508.  * Side effects:
  1509.  *    Fills in the access time, modify time, and size from information
  1510.  *    we have cached here.
  1511.  *
  1512.  *----------------------------------------------------------------------
  1513.  */
  1514. /*ARGSUSED*/
  1515. ReturnStatus
  1516. FsrmtFileGetIOAttr(fileIDPtr, clientID, attrPtr)
  1517.     Fs_FileID        *fileIDPtr;    /* ID on the file */
  1518.     int            clientID;    /* Host ID of calling process */
  1519.     Fs_Attributes    *attrPtr;    /* Attributes to update */
  1520. {
  1521.     Fsrmt_FileIOHandle *handlePtr;
  1522.  
  1523.     handlePtr = Fsutil_HandleFetchType(Fsrmt_FileIOHandle, fileIDPtr);
  1524.     if (handlePtr != (Fsrmt_FileIOHandle *)NIL) {
  1525.     Fscache_UpdateAttrFromCache(&handlePtr->cacheInfo, attrPtr);
  1526.     Fsutil_HandleRelease(handlePtr, TRUE);
  1527.     }
  1528.     return(SUCCESS);
  1529. }
  1530.  
  1531. /*
  1532.  *----------------------------------------------------------------------
  1533.  *
  1534.  * FsrmtFileSetIOAttr --
  1535.  *
  1536.  *    Set the attributes of a remotely served file.  This routine is
  1537.  *    called after the file server has been contacted, so its only
  1538.  *    job is to update attributes we have cached here on the client.
  1539.  *
  1540.  * Results:
  1541.  *    SUCCESS or FS_STALE_HANDLE.
  1542.  *
  1543.  * Side effects:
  1544.  *    Updates the access time, modify time, and size that
  1545.  *    we have cached here.
  1546.  *
  1547.  *----------------------------------------------------------------------
  1548.  */
  1549. /*ARGSUSED*/
  1550. ReturnStatus
  1551. FsrmtFileSetIOAttr(fileIDPtr, attrPtr, flags)
  1552.     Fs_FileID        *fileIDPtr;    /* ID on the file */
  1553.     Fs_Attributes    *attrPtr;    /* Attributes to update */
  1554.     int            flags;        /* What attrs to set */
  1555. {
  1556.     Fsrmt_FileIOHandle *handlePtr;
  1557.  
  1558.     handlePtr = Fsutil_HandleFetchType(Fsrmt_FileIOHandle, fileIDPtr);
  1559.     if (handlePtr != (Fsrmt_FileIOHandle *)NIL) {
  1560.     Fscache_UpdateCachedAttr(&handlePtr->cacheInfo, attrPtr, flags);
  1561.     Fsutil_HandleRelease(handlePtr, TRUE);
  1562.     }
  1563.     return(SUCCESS);
  1564. }
  1565.  
  1566. static void FsrmtCleanBlocks _ARGS_((ClientData    data,
  1567.                 Proc_CallInfo *callInfoPtr));
  1568.  
  1569.  
  1570. /*
  1571.  *----------------------------------------------------------------------
  1572.  *
  1573.  * FsrmtStartWriteBack --
  1574.  *
  1575.  *     Start a block cleaner process for the specified domain.
  1576.  *
  1577.  * Results:
  1578.  *    TRUE if a block cleaner was started.
  1579.  *
  1580.  * Side effects:
  1581.  *    Number of block cleaner processes may be incremented.
  1582.  *
  1583.  * ----------------------------------------------------------------------------
  1584.  */
  1585. static Boolean
  1586. FsrmtStartWriteBack(backendPtr)
  1587.     Fscache_Backend *backendPtr;    /* Backend to start writeback. */
  1588. {
  1589.     LOCK_MONITOR;
  1590.  
  1591.     if (fsrmtBlockCleaners < fscache_MaxBlockCleaners) {
  1592.     Proc_CallFunc(FsrmtCleanBlocks, (ClientData) backendPtr, 0);
  1593.     fsrmtBlockCleaners++;
  1594.     UNLOCK_MONITOR;
  1595.     return TRUE;
  1596.     }
  1597.     UNLOCK_MONITOR;
  1598.     return FALSE;
  1599. }
  1600.  
  1601.  
  1602. /*
  1603.  * ----------------------------------------------------------------------------
  1604.  *
  1605.  *    Functions to clean dirty blocks.
  1606.  *
  1607.  * ----------------------------------------------------------------------------
  1608.  */
  1609.  
  1610.  
  1611. /*
  1612.  * ----------------------------------------------------------------------------
  1613.  *
  1614.  * FsrmtCleanBlocks
  1615.  *
  1616.  *    Write all blocks on the dirty list to disk.  Called either from
  1617.  *    a block cleaner process or synchronously during system shutdown.
  1618.  *
  1619.  * Results:
  1620.  *         None.
  1621.  *
  1622.  * Side effects:
  1623.  *         The dirty list is emptied.
  1624.  *
  1625.  * ----------------------------------------------------------------------------
  1626.  */
  1627. /*ARGSUSED*/
  1628. static void
  1629. FsrmtCleanBlocks(data, callInfoPtr)
  1630.     ClientData        data;        /* Background flag.  If TRUE it means
  1631.                      * we are called from a block cleaner
  1632.                      * process.  Otherwise we being called
  1633.                      * synchrounously during a shutdown */
  1634.     Proc_CallInfo    *callInfoPtr;    /* Not Used. */
  1635. {
  1636.     Fscache_Block    *blockPtr;
  1637.     ReturnStatus        status;
  1638.     int                lastDirtyBlock;
  1639.     Fscache_FileInfo        *cacheInfoPtr;
  1640.     Fscache_Backend        *backendPtr;
  1641.  
  1642.     backendPtr = (Fscache_Backend *) data;
  1643.     cacheInfoPtr = Fscache_GetDirtyFile(backendPtr, TRUE, 
  1644.         FileMatch, (ClientData) 0);
  1645.     while (cacheInfoPtr != (Fscache_FileInfo *)NIL) {
  1646.     blockPtr = Fscache_GetDirtyBlock(cacheInfoPtr, BlockMatch,
  1647.             (ClientData) 0,  &lastDirtyBlock);
  1648.     while (blockPtr != (Fscache_Block *) NIL) {
  1649.         /*
  1650.          * Write the block.
  1651.          */
  1652. #ifdef SOSP91
  1653.         Fscache_AddBlockToStats(cacheInfoPtr, blockPtr);
  1654. #endif SOSP91
  1655.         status = backendPtr->ioProcs.blockWrite
  1656.             (cacheInfoPtr->hdrPtr, blockPtr, lastDirtyBlock);
  1657.         Fscache_ReturnDirtyBlock( blockPtr, status);
  1658.         blockPtr = Fscache_GetDirtyBlock(cacheInfoPtr, BlockMatch,
  1659.             (ClientData) 0, &lastDirtyBlock);
  1660.     }
  1661. #ifdef SOSP91
  1662.     cacheInfoPtr->flags &= ~FSCACHE_REASON_FLAGS;
  1663. #endif SOSP91
  1664.     Fscache_ReturnDirtyFile(cacheInfoPtr, FALSE);
  1665.     cacheInfoPtr = Fscache_GetDirtyFile(backendPtr, TRUE,
  1666.             FileMatch, (ClientData) 0);
  1667.     }
  1668.     FscacheBackendIdle(backendPtr);
  1669.     LOCK_MONITOR;
  1670.     fsrmtBlockCleaners--;
  1671.     UNLOCK_MONITOR;
  1672. }
  1673.  
  1674.  
  1675.  
  1676. /*
  1677.  * ----------------------------------------------------------------------------
  1678.  *
  1679.  * FsrmtReallocBlock --
  1680.  *
  1681.  *     Reallocate a block which got a write error.
  1682.  *
  1683.  * Results:
  1684.  *    None.
  1685.  *
  1686.  * Side effects:
  1687.  *
  1688.  * ----------------------------------------------------------------------------
  1689.  */
  1690. /*ARGSUSED*/
  1691. static void
  1692. FsrmtReallocBlock(data, callInfoPtr)
  1693.     ClientData        data;            /* Block to move */
  1694.     Proc_CallInfo    *callInfoPtr;        /* Not used. */
  1695. {
  1696.     panic("FsrmtReallocBlock called\n");
  1697. }
  1698.  
  1699. /*
  1700.  * ----------------------------------------------------------------------------
  1701.  *
  1702.  * BlockMatch --
  1703.  *
  1704.  *     Cache backend block type match.  Fsrmt doesn't care about the 
  1705.  *    order of blocks returned by GetDirtyBlocks.
  1706.  *
  1707.  * Results:
  1708.  *    TRUE.
  1709.  *
  1710.  * Side effects:
  1711.  *
  1712.  * ----------------------------------------------------------------------------
  1713.  */
  1714. /*ARGSUSED*/
  1715. static Boolean
  1716. BlockMatch( blockPtr, cleintData)
  1717.     Fscache_Block *blockPtr;
  1718.     ClientData    cleintData;
  1719. {
  1720.     return TRUE;
  1721. }
  1722.  
  1723. /*
  1724.  * ----------------------------------------------------------------------------
  1725.  *
  1726.  * FileMatch --
  1727.  *
  1728.  *     Cache backend files match.  Fsrmt doesn't care about the 
  1729.  *    order of files returned by GetDirtyFiles.
  1730.  *
  1731.  * Results:
  1732.  *    TRUE.
  1733.  *
  1734.  * Side effects:
  1735.  *
  1736.  * ----------------------------------------------------------------------------
  1737.  */
  1738. /*ARGSUSED*/
  1739. static Boolean
  1740. FileMatch( cacheInfoPtr, cleintData)
  1741.     Fscache_FileInfo *cacheInfoPtr;
  1742.     ClientData    cleintData;
  1743. {
  1744.     return TRUE;
  1745. }
  1746.